#include <SDL/SDL.h>
#include <assert.h>
#include <unistd.h>
#include <SDL/SDL_image.h>
#include <SDL/SDL_mutex.h>

//Time between two updates
#define UPDATE_TIME_MS 16
//Time between painting two screens
#define DISPLAY_TIME_MS 35

int quit = 0;
float pos = 0.0f;
SDL_Surface *img, *scr;
SDL_mutex *data_mutex;

void blit_tiles(SDL_Surface *img, SDL_Surface *scr, int x_tile_offset = 0, const int tiles_per_row = 16) {
  SDL_Rect src, dest;

  src.x = x_tile_offset;
  src.w = 16;
  src.h = 16;
  dest.w = 16;
  dest.h = 16;
  for(int ii = 0; ii < img->h; ii += 16) {
    int i = ii / 16;
    int x = i % tiles_per_row;
    int y = i / tiles_per_row;

    src.y = ii;
    dest.x = 800 - 320 + x * 19;
    dest.y = 400 - 300 + y * 18;
    SDL_BlitSurface(img, &src, scr, &dest);
  }
}

int update_thread(void *none) {
  while(true) {
    printf("update: %ld\n", (long)SDL_GetTicks());
    SDL_mutexP(data_mutex);
    pos += 10 * UPDATE_TIME_MS/1000.0f;
    if(pos > 639) pos = 0;
    SDL_mutexV(data_mutex);
    SDL_Delay(UPDATE_TIME_MS);
  }
}

int draw_thread(void *none) {
  Uint32 last_display_ticks = 0;

  do {
    printf("display: %ld\n", (long)SDL_GetTicks());
    SDL_mutexP(data_mutex);
    SDL_Rect rect = { pos, 350, 30, 30 };
    SDL_mutexV(data_mutex);
    SDL_FillRect(scr, NULL, SDL_MapRGB(scr->format, 0, 0, 0));
    SDL_FillRect(scr, &rect, SDL_MapRGB(scr->format, 0x11, 0x33, 0x6a));
    SDL_Flip(scr);
    Uint32 now = SDL_GetTicks(); //At the end of the loop!
    Uint32 new_delta = last_display_ticks + DISPLAY_TIME_MS - now;
    if(new_delta < 200) SDL_Delay(new_delta);
    SDL_Delay(DISPLAY_TIME_MS);
  } while(true);
}

int main(int argc, char **argv) {
  SDL_Event event;
  Uint32 last_ticks = 0;

  assert(SDL_Init(SDL_INIT_VIDEO) == 0);
  scr = SDL_SetVideoMode(640, 400, 8, SDL_HWSURFACE|SDL_ANYFORMAT|SDL_DOUBLEBUF);
  assert(scr);
  assert(data_mutex = SDL_CreateMutex());
  SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE); //Ignore all mouse movements...

  SDL_CreateThread(update_thread, NULL);
  SDL_CreateThread(draw_thread, NULL);
  while(!quit) {
    SDL_WaitEvent(&event);
    switch(event.type) {
    case SDL_QUIT:
      quit = 2;
      break;
    case SDL_MOUSEBUTTONDOWN:
    case SDL_MOUSEBUTTONUP:
      printf("button=%d state=%d x=$%04hX y=$%04hX\n", event.button.button, event.button.state, event.button.x, event.button.y);
      break;
    case SDL_KEYDOWN:
    case SDL_KEYUP:
      printf("state=%d sym=$%04X\n", event.key.state, event.key.keysym.sym);
      break;
    default:
      printf("event.type = $%x\n", (unsigned int)event.type);
    }
    printf("event: %ld\n", (long)SDL_GetTicks());
  }
  SDL_Quit();
  return 0;
}

// g++ frameratethreads.cc -lSDL -lSDL_image -lpthread
